home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / mint104s.zoo / mint.src / unifs.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  13KB  |  618 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith.
  3. Copyright 1992 Atari Corporation.
  4. All rights reserved.
  5.  */
  6.  
  7. /* a simple unified file system */
  8.  
  9. #include "mint.h"
  10.  
  11.  
  12. extern FILESYS bios_filesys, proc_filesys, pipe_filesys, shm_filesys;
  13.  
  14. static long    ARGS_ON_STACK uni_root    P_((int drv, fcookie *fc));
  15. static long    ARGS_ON_STACK uni_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  16. static long    ARGS_ON_STACK uni_getxattr    P_((fcookie *fc, XATTR *xattr));
  17. static long    ARGS_ON_STACK uni_chattr    P_((fcookie *fc, int attrib));
  18. static long    ARGS_ON_STACK uni_chown    P_((fcookie *fc, int uid, int gid));
  19. static long    ARGS_ON_STACK uni_chmode    P_((fcookie *fc, unsigned mode));
  20. static long    ARGS_ON_STACK uni_rmdir    P_((fcookie *dir, const char *name));
  21. static long    ARGS_ON_STACK uni_remove    P_((fcookie *dir, const char *name));
  22. static long    ARGS_ON_STACK uni_getname    P_((fcookie *root, fcookie *dir,
  23.                             char *pathname, int size));
  24. static long    ARGS_ON_STACK uni_rename    P_((fcookie *olddir, char *oldname,
  25.                     fcookie *newdir, const char *newname));
  26. static long    ARGS_ON_STACK uni_opendir    P_((DIR *dirh, int flags));
  27. static long    ARGS_ON_STACK uni_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *));
  28. static long    ARGS_ON_STACK uni_rewinddir    P_((DIR *dirh));
  29. static long    ARGS_ON_STACK uni_closedir    P_((DIR *dirh));
  30. static long    ARGS_ON_STACK uni_pathconf    P_((fcookie *dir, int which));
  31. static long    ARGS_ON_STACK uni_dfree    P_((fcookie *dir, long *buf));
  32. static DEVDRV *    ARGS_ON_STACK uni_getdev    P_((fcookie *fc, long *devsp));
  33. static long    ARGS_ON_STACK uni_symlink    P_((fcookie *dir, const char *name, const char *to));
  34. static long    ARGS_ON_STACK uni_readlink    P_((fcookie *fc, char *buf, int buflen));
  35.  
  36. FILESYS uni_filesys = {
  37.     (FILESYS *)0,
  38.     FS_LONGPATH,
  39.     uni_root,
  40.     uni_lookup, nocreat, uni_getdev, uni_getxattr,
  41.     uni_chattr, uni_chown, uni_chmode,
  42.     nomkdir, uni_rmdir, uni_remove, uni_getname, uni_rename,
  43.     uni_opendir, uni_readdir, uni_rewinddir, uni_closedir,
  44.     uni_pathconf, uni_dfree, nowritelabel, noreadlabel,
  45.     uni_symlink, uni_readlink, nohardlink, nofscntl, nodskchng
  46. };
  47.  
  48. /*
  49.  * structure that holds files
  50.  * if (mode & S_IFMT == S_IFDIR), then this is an alias for a drive:
  51.  *    "dev" holds the appropriate BIOS device number, and
  52.  *    "data" is meaningless
  53.  * if (mode & S_IFMT == S_IFLNK), then this is a symbolic link:
  54.  *    "dev" holds the user id of the owner, and
  55.  *    "data" points to the actual link data
  56.  */
  57.  
  58. typedef struct unifile {
  59.     char name[NAME_MAX+1];
  60.     ushort mode;
  61.     ushort dev;
  62.     FILESYS *fs;
  63.     void *data;
  64.     struct unifile *next;
  65. } UNIFILE;
  66.  
  67. static UNIFILE u_drvs[UNI_NUM_DRVS];
  68. static UNIFILE *u_root = 0;
  69.  
  70. void
  71. unifs_init()
  72. {
  73.     UNIFILE *u = u_drvs;
  74.     int i;
  75.  
  76.     u_root = u;
  77.     for (i = 0; i < UNI_NUM_DRVS; i++,u++) {
  78.         u->next = u+1;
  79.         u->mode = S_IFDIR|DEFAULT_DIRMODE;
  80.         u->dev = i;
  81.         if (i == PROCDRV) {
  82.             strcpy(u->name, "proc");
  83.             u->fs = &proc_filesys;
  84.         } else if (i == PIPEDRV) {
  85.             strcpy(u->name, "pipe");
  86.             u->fs = &pipe_filesys;
  87.         } else if (i == BIOSDRV) {
  88.             strcpy(u->name, "dev");
  89.             u->fs = &bios_filesys;
  90.         } else if (i == UNIDRV) {
  91.             (u-1)->next = u->next;    /* skip this drive */
  92.         } else if (i == SHMDRV) {
  93.             strcpy(u->name, "shm");
  94.             u->fs = &shm_filesys;
  95.         } else {
  96.             u->name[0] = i + 'a';
  97.             u->name[1] = 0;
  98.             u->fs = 0;
  99.         }
  100.     }
  101.     --u;    /* oops, we went too far */
  102.     u->next = 0;
  103. }
  104.  
  105. static long ARGS_ON_STACK 
  106. uni_root(drv, fc)
  107.     int drv;
  108.     fcookie *fc;
  109. {
  110.     if (drv == UNIDRV) {
  111.         fc->fs = &uni_filesys;
  112.         fc->dev = drv;
  113.         fc->index = 0L;
  114.         return 0;
  115.     }
  116.     fc->fs = 0;
  117.     return EINTRN;
  118. }
  119.  
  120. static long ARGS_ON_STACK 
  121. uni_lookup(dir, name, fc)
  122.     fcookie *dir;
  123.     const char *name;
  124.     fcookie *fc;
  125. {
  126.     UNIFILE *u;
  127.     long drvs;
  128.     FILESYS *fs;
  129.     fcookie *tmp;
  130.     extern long dosdrvs;
  131.  
  132.     TRACE(("uni_lookup(%s)", name));
  133.  
  134.     if (dir->index != 0) {
  135.         DEBUG(("uni_lookup: bad directory"));
  136.         return EPTHNF;
  137.     }
  138. /* special case: an empty name in a directory means that directory */
  139. /* so do "." and ".." */
  140.  
  141.     if (!*name || !strcmp(name, ".") || !strcmp(name, "..")) {
  142.         dup_cookie(fc, dir);
  143.         return 0;
  144.     }
  145.     drvs = drvmap() | dosdrvs | PSEUDODRVS;
  146. /*
  147.  * OK, check the list of aliases and special directories
  148.  */
  149.     for (u = u_root; u; u = u->next) {
  150.         if (!stricmp(name, u->name)) {
  151.             if ( (u->mode & S_IFMT) == S_IFDIR ) {
  152.                 if (u->dev >= NUM_DRIVES) {
  153.                     fs = u->fs;
  154.                     return (*fs->root)(u->dev,fc);
  155.                 }
  156.                 if ((drvs & (1L << u->dev)) == 0)
  157.                     return EPTHNF;
  158.                 tmp = &curproc->root[u->dev];
  159.                 if (!tmp->fs) {        /* drive changed? */
  160.                     changedrv(tmp->dev);
  161.                     tmp = &curproc->root[u->dev];
  162.                     if (!tmp->fs)
  163.                         return EPTHNF;
  164.                 }
  165.                 dup_cookie(fc, tmp);
  166.             } else {        /* a symbolic link */
  167.                 fc->fs = &uni_filesys;
  168.                 fc->dev = UNIDRV;
  169.                 fc->index = (long)u;
  170.             }
  171.             return 0;
  172.         }
  173.     }
  174.     DEBUG(("uni_lookup: name (%s) not found", name));
  175.     return EFILNF;
  176. }
  177.  
  178. static long ARGS_ON_STACK 
  179. uni_getxattr(fc, xattr)
  180.     fcookie *fc;
  181.     XATTR *xattr;
  182. {
  183.     UNIFILE *u = (UNIFILE *)fc->index;
  184.  
  185.     if (fc->fs != &uni_filesys) {
  186.         ALERT("ERROR: wrong file system getxattr called");
  187.         return EINTRN;
  188.     }
  189.  
  190.     xattr->index = fc->index;
  191.     xattr->dev = fc->dev;
  192.     xattr->nlink = 1;
  193.     xattr->blksize = 1;
  194.  
  195. /* If "u" is null, then we have the root directory, otherwise
  196.  * we use the UNIFILE structure to get the info about it
  197.  */
  198.     if (!u || ( (u->mode & S_IFMT) == S_IFDIR )) {
  199.         xattr->uid = xattr->gid = 0;
  200.         xattr->size = xattr->nblocks = 0;
  201.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  202.         xattr->attr = FA_DIR;
  203.     } else {
  204.         xattr->uid = u->dev;
  205.         xattr->gid = 0;
  206.         xattr->size = xattr->nblocks = strlen(u->data) + 1;
  207.         xattr->mode = u->mode;
  208.         xattr->attr = 0;
  209.     }
  210.     xattr->mtime = xattr->atime = xattr->ctime = 0;
  211.     xattr->mdate = xattr->adate = xattr->cdate = 0;
  212.     return 0;
  213. }
  214.  
  215. static long ARGS_ON_STACK 
  216. uni_chattr(dir, attrib)
  217.     fcookie *dir;
  218.     int attrib;
  219. {
  220.     UNUSED(dir); UNUSED(attrib);
  221.     return EACCDN;
  222. }
  223.  
  224. static long ARGS_ON_STACK 
  225. uni_chown(dir, uid, gid)
  226.     fcookie *dir;
  227.     int uid, gid;
  228. {
  229.     UNUSED(dir); UNUSED(uid);
  230.     UNUSED(gid);
  231.     return EINVFN;
  232. }
  233.  
  234. static long ARGS_ON_STACK 
  235. uni_chmode(dir, mode)
  236.     fcookie *dir;
  237.     unsigned mode;
  238. {
  239.     UNUSED(dir);
  240.     UNUSED(mode);
  241.     return EINVFN;
  242. }
  243.  
  244. static long ARGS_ON_STACK 
  245. uni_rmdir(dir, name)
  246.     fcookie *dir;
  247.     const char *name;
  248. {
  249.     long r;
  250.  
  251.     r = uni_remove(dir, name);
  252.     if (r == EFILNF) r = EPTHNF;
  253.     return r;
  254. }
  255.  
  256. static long ARGS_ON_STACK 
  257. uni_remove(dir, name)
  258.     fcookie *dir;
  259.     const char *name;
  260. {
  261.     UNIFILE *u, *lastu;
  262.  
  263.     UNUSED(dir);
  264.  
  265.     lastu = 0;
  266.     u = u_root;
  267.     while (u) {
  268.         if (!strncmp(u->name, name, NAME_MAX)) {
  269.             if ( (u->mode & S_IFMT) != S_IFLNK ) return EFILNF;
  270.             kfree(u->data);
  271.             if (lastu)
  272.                 lastu->next = u->next;
  273.             else
  274.                 u_root = u->next;
  275.             kfree(u);
  276.             return 0;
  277.         }
  278.         lastu = u;
  279.         u = u->next;
  280.     }
  281.     return EFILNF;
  282. }
  283.  
  284. static long ARGS_ON_STACK 
  285. uni_getname(root, dir, pathname, size)
  286.     fcookie *root, *dir; char *pathname;
  287.     int size;
  288. {
  289.     FILESYS *fs;
  290.     UNIFILE *u;
  291.     char *n;
  292.     fcookie relto;
  293.     char tmppath[PATH_MAX];
  294.     long r;
  295.  
  296.     UNUSED(root);
  297.  
  298.     if (size <= 0) return ERANGE;
  299.  
  300.     fs = dir->fs;
  301.     if (dir->dev == UNIDRV) {
  302.         *pathname = 0;
  303.         return 0;
  304.     }
  305.  
  306.     for (u = u_root; u; u = u->next) {
  307.         if (dir->dev == u->dev && (u->mode & S_IFMT) == S_IFDIR) {
  308.             *pathname++ = '\\';
  309.             if (--size <= 0) return ERANGE;
  310.             for (n = u->name; *n; ) {
  311.                 *pathname++ = *n++;
  312.                 if (--size <= 0) return ERANGE;
  313.             }
  314.             break;
  315.         }
  316.     }
  317.  
  318.     if (!u) {
  319.         ALERT("unifs: couldn't match a drive with a directory");
  320.         return EPTHNF;
  321.     }
  322.  
  323.     if (dir->dev >= NUM_DRIVES) {
  324.         if ((*fs->root)(dir->dev, &relto) == 0) {
  325.             if (!(fs->fsflags & FS_LONGPATH)) {
  326.                 r = (*fs->getname)(&relto, dir, tmppath, PATH_MAX);
  327.                 release_cookie(&relto);
  328.                 if (r) {
  329.                     return r;
  330.                 }
  331.                 if (strlen(tmppath) < size) {
  332.                     strcpy(pathname, tmppath);
  333.                     return 0;
  334.                 } else {
  335.                     return ERANGE;
  336.                 }
  337.             }
  338.             r = (*fs->getname)(&relto, dir, pathname, size);
  339.             release_cookie(&relto);
  340.             return r;
  341.         } else {
  342.             *pathname = 0;
  343.             return EINTRN;
  344.         }
  345.     }